package com.het.monitor.util;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import com.het.monitor.config.Apps;
import com.het.monitor.task.model.AppConf;
import com.jcraft.jsch.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.io.*;

@Slf4j
@Data
@Component
public class ConnLinuxServerUtil {
    // 字符编码
    private static String DEFAULTCHART = "UTF-8";

    private Connection connection;

    private static ChannelSftp sftp = null;

    public boolean connLinuxServer(Apps apps) {
        boolean flag = false;
        try {
            // 创建连接对象
            connection = new Connection(apps.getIp());
            connection.connect();
            //判断身份是否已经认证
            if (!connection.isAuthenticationComplete()) {
                //加锁，防止多线程调用时线程间判断不一致，导致出现重复认证
                synchronized (this) {
                    if (!connection.isAuthenticationComplete()) {
                        // 验证用户名 密码
                        flag = connection.authenticateWithPassword(apps.getUName(), apps.getUPwd());
                    }
                }
            }

        } catch (IOException e) {
            log.info("服务器IP:{},checkcmd:{}, error:{}",apps.getIp(),apps.getCheckCmd(),e.getMessage());
            return false;
        }
        return flag;
    }
    /**
     * 连接linux服务器方法
     *
     * @return
     */
    public boolean connLinuxServer(String ip, String uName, String uPwd) {
        boolean flag = false;
        try {
            // 创建连接对象
            connection = new Connection(ip);
            connection.connect();
            // 验证用户名 密码
            flag = connection.authenticateWithPassword(uName, uPwd);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }
    /**
     * 执行linux脚本
     *
     * @param cmd
     * @return
     */
    public String execute(String cmd, Apps apps) {
        String result = "";
        try {
            // 如果登录成功的话
            if (connLinuxServer(apps)) {
                //打开一个会话
                Session session = connection.openSession();
                // 执行输入进来的命令 可以是linux命令 也可以是sh命令 执行sh脚本
                session.execCommand(cmd);
                result = processStdout(session.getStdout(), DEFAULTCHART);
                //如果为得到标准输出为空，说明脚本执行出错了
                if (StringUtils.isBlank(result)) {
                    result = processStdout(session.getStderr(), DEFAULTCHART);
                }
//                log.info("{}，{} 执行结果：{}",apps.getIp(), cmd, result);
                // 关闭session对话
                session.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭连接
            connection.close();
        }
//         返回结果
        return result;
    }
    /**
     * 解析执行命令结果
     *
     * @param stdout
     * @param defaultchart
     * @return
     */
    public String processStdout(InputStream stdout, String defaultchart) {
        // 把session的标准输出包装成InputStream，用于接收目标服务器上的控制台返回结果，
        // 读取br中的内容。然后在循环中，把每一行的内容添加到StringBuffer里面。
        InputStream in = new StreamGobbler(stdout);
        StringBuffer stringBuffer = new StringBuffer();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(in, defaultchart));
            String line;
            while ((line = br.readLine()) != null) {
                if (!ObjectUtils.isEmpty(line) && !"1".equals(line)) {
                    stringBuffer.append("\n"+line );
                } else {
                    stringBuffer.append(line);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 返回结果 形式为字符串
        return stringBuffer.toString().replaceFirst("\n","");
    }

    public Boolean monitor(ConnLinuxServerUtil connLinuxServerUtil, AppConf appConf, String doCmd, String areaType, String secret) {
        Apps con = Apps.builder().ip(appConf.getIp()).uName(appConf.getUser()).uPwd(AESUtil.decrypt(appConf.getPwd(), secret)).build();
        String result = connLinuxServerUtil.execute(doCmd, con);
        log.info(result + "--------------------------------------");
        if (result.equals("")) {
            log.info("------------------------------------------------------------------------------------");
            log.info("【告警】{},检查到:{}-{},IP:{},服务器异常未启动：{} ， 结果：{}",areaType, appConf.getAppName(), appConf.getAppJar(), appConf.getIp(), appConf.getCheckCmd(), result);
        }
        if ("1".equals(result) || result == "1" || result.equals("")) {
            log.info("【告警】{},检查到:{}-{},IP:{},服务未启动：{} ， 结果：{}",areaType, appConf.getAppName(), appConf.getAppJar(), appConf.getIp(), appConf.getCheckCmd(), result);
        } else {
            log.info("【正常】{}:检查【{}-{},ip:{}】服务启动正常",areaType, appConf.getAppName(), appConf.getAppJar(), appConf.getIp());
            return true;
        }
        return false;
    }
}